package com.ruoyi.central.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.ruoyi.cache.common.CacheConstants;
import com.ruoyi.central.domain.TopCentralProductRelation;
import com.ruoyi.central.domain.core.ProductTree;
import com.ruoyi.central.service.ITopCentralProductRelationService;
import com.ruoyi.common.core.domain.Tree;
import com.ruoyi.central.enums.ProductMaterialType;
import com.ruoyi.common.utils.bean.EnumUtils;
import lombok.extern.slf4j.Slf4j;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;
import org.springframework.stereotype.Service;
import com.ruoyi.common.core.service.ServiceImpl;
import com.ruoyi.central.mapper.TopCentralProductTypeMapper;
import com.ruoyi.central.domain.TopCentralProductType;
import com.ruoyi.central.service.ITopCentralProductTypeService;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.enums.common.State;

import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;

/**
 * 产品类型Service业务层处理
 *
 * @author ruoyi
 * @date 2022-03-02
 */
@Service
@Slf4j
@CacheConfig(cacheNames = CacheConstants.EhcacheName.CONTINUAL_CACHE_NAME)
public class TopCentralProductTypeServiceImpl extends ServiceImpl<TopCentralProductTypeMapper,TopCentralProductType> implements ITopCentralProductTypeService
{
    @Autowired
    private ITopCentralProductRelationService productRelationService;

    /**
     * 查询产品类型
     * 
     * @param id 产品类型主键
     * @param columns 查询指定的列
     * @return 产品类型
     */
    @Override
    public TopCentralProductType selectById(Integer id, SFunction<TopCentralProductType,?> ... columns){

        if(StringUtils.isNotEmpty(columns)){
            return selectOne(lambdaQuery().select(columns).eq(TopCentralProductType::getId,id));
        }
        return super.selectById(id);
    }

    /**
     * 查询产品类型
         * 注意：只获取状态信息为可用的数据
     * 
     * @param id 产品类型主键
     * @param columns 查询指定的列
     * @return 产品类型
     */
    @Override
    public TopCentralProductType selectUsableById(Integer id, SFunction<TopCentralProductType,?> ... columns)
    {
            LambdaQueryWrapper<TopCentralProductType> lambdaQueryWrapper = lambdaQuery().eq(TopCentralProductType::getId,id);
            buildUsableState(lambdaQueryWrapper);
            if(StringUtils.isNotEmpty(columns)){
                lambdaQueryWrapper.select(columns);
            }
            return selectOne(lambdaQueryWrapper);
    }

    /**
     * 查询产品类型列表
     *
     * @param topCentralProductType 产品类型
     * @return 产品类型
     */
    @Override
    public List<TopCentralProductType> selectList(TopCentralProductType topCentralProductType)
    {
        return getBaseMapper().selectTopCentralProductTypeList(topCentralProductType);
    }

    /**
     * 获取所有的产品类型数据
     * 
     * @return Map<Integer,TopCentralProductType> 集合
     */
    @Cacheable
    @Override
    public Map<Integer,TopCentralProductType> selectAllMap(){

        return getBaseMapper().selectList(customLambdaQuery())
                .stream().collect(Collectors.toMap(TopCentralProductType::getId,v->v));
    }

    /**
     * 新增产品类型
     *
     * @param topCentralProductType 产品类型
     * @return 结果
     */
    @CacheEvict(keyGenerator=CacheConstants.KeyGeneratorName.EHCACHE_KEY_GENERATOR_EVICT)
    @Override
    public boolean insert(TopCentralProductType topCentralProductType)
    {
        return super.insert(topCentralProductType);
    }

    /**
     * 新增（批量）产品类型
     *
     * @param topCentralProductTypeList 实体对象集合
     */
    @CacheEvict(keyGenerator=CacheConstants.KeyGeneratorName.EHCACHE_KEY_GENERATOR_EVICT)
    @Override
    public boolean insertBatch(Collection<TopCentralProductType> topCentralProductTypeList, int batchSize) {
        return super.insertBatch(topCentralProductTypeList, batchSize);
    }

    /**
     * 删除 产品类型 根据编号
     * @param id
     * @return true 删除成功 false 删除失败
     */
    @CacheEvict(keyGenerator=CacheConstants.KeyGeneratorName.EHCACHE_KEY_GENERATOR_EVICT)
    @Override
    public boolean deleteById(Serializable id) {
        return super.deleteById(id);
    }

    /**
     * 批量删除 产品类型 根据 编号集合
     * @param ids
     * @return true 删除成功 false 删除失败
     */
    @CacheEvict(keyGenerator=CacheConstants.KeyGeneratorName.EHCACHE_KEY_GENERATOR_EVICT)
    @Override
    public boolean deleteByIds(Collection<? extends Serializable> ids) {
        return super.deleteByIds(ids);
    }

    /**
     * 批量修改 产品类型 根据唯一编号
     * @param topCentralProductTypeList
     * @param batchSize  更新批次数量
     * @return true 修改成功 false 修改失败
     */
    @CacheEvict(keyGenerator=CacheConstants.KeyGeneratorName.EHCACHE_KEY_GENERATOR_EVICT)
    @Override
    public boolean updateBatchById(Collection<TopCentralProductType> topCentralProductTypeList, int batchSize) {
        return super.updateBatchById(topCentralProductTypeList, batchSize);
    }

    /**
     * 修改 产品类型
     * @param  topCentralProductType
     * @param updateWrapper
     * @return
     */
    @CacheEvict(keyGenerator=CacheConstants.KeyGeneratorName.EHCACHE_KEY_GENERATOR_EVICT)
    @Override
    public boolean update(TopCentralProductType topCentralProductType, LambdaUpdateWrapper<TopCentralProductType> updateWrapper) {
        return super.update(topCentralProductType,updateWrapper);
    }

    /**
     * 修改产品类型
     *
     * @param topCentralProductType 产品类型
     * @return 结果
     */
    @CacheEvict(keyGenerator=CacheConstants.KeyGeneratorName.EHCACHE_KEY_GENERATOR_EVICT)
    @Override
    public boolean updateById(TopCentralProductType topCentralProductType)
    {
        return super.updateById(topCentralProductType);
    }

    /**
     * 修改产品类型状态 根据 id 产品类型
     * 
     * @param id 产品类型主键
     * @param state 数据状态
     * @return 结果
     */
    @CacheEvict(keyGenerator=CacheConstants.KeyGeneratorName.EHCACHE_KEY_GENERATOR_EVICT)
    @Override
    public boolean updateStateById(Integer id, State state){

        return updateById(buildTopCentralProductTypeForUpdateState(id,state));
    }

    /**
     * 修改多个产品类型状态 根据 id 产品类型
     * 
     * @param ids 产品类型主键
     * @param state 数据状态
     * @return 结果
     */
    @CacheEvict(keyGenerator=CacheConstants.KeyGeneratorName.EHCACHE_KEY_GENERATOR_EVICT)
    @Override
    public boolean updateStateByIds(Collection<Integer> ids, State state){

        List<TopCentralProductType> updateTopCentralProductTypeList = new ArrayList(ids.size());

            ids.forEach(id->updateTopCentralProductTypeList.add(buildTopCentralProductTypeForUpdateState(id,state)));

        return updateBatchById(updateTopCentralProductTypeList);
    }

    /**
     * 获取某一个类型的合成树状数据结构
     * @param productTypeId
     * @return 当前产品类型的合成产品树
     */
    @Override
    public ProductTree productTypeTreeData(Integer productTypeId) {

        return initProductTree(productTypeId);

    }
    /**
     * 获取所有最终产品类型的合成树状数据结构
     * @return 所有产品类型的合成产品树 集合
     */
    @Cacheable
    @Override
    public Map<Integer,Tree<TopCentralProductType>> productTypeTreeAll(){

        Map<Integer, TopCentralProductType> productTypeMap = selectAllMap();

        //获取所有root产品列表
        List<TopCentralProductType> productTypes = productTypeMap.values().stream().filter(productType -> EnumUtils.equals(ProductMaterialType.FINISHED_PRODUCT,productType.getProductMaterialTypeId())).collect(Collectors.toList());

        //获取所有的产品关系数据
        Map<Integer, List<TopCentralProductRelation>> productRelationGroupMap = productRelationService.selectAllMap().values()
                .stream().collect(Collectors.groupingBy(TopCentralProductRelation::getProductTypeId));

        Map<Integer,Tree<TopCentralProductType>> treeMap = new HashMap<>(productTypes.size());

        for (TopCentralProductType productType : productTypes) {

            Tree<TopCentralProductType> productTypeTree = new Tree<>(productType.getId(),productType.getName(),productType);

            fillParts(productTypeTree,productTypeMap,productRelationGroupMap);

            treeMap.put(productType.getId(),productTypeTree);

        }
        return treeMap;
    }

    /**
     * 递归获取合成产品的子类
     * @param rootTree 合成产品
     * @param productTypeMap 所有零件、产品、半成品 类型对象
     * @param productRelationGroupMap 所有产品关系对象
     */
    private void fillParts(Tree<TopCentralProductType> rootTree,Map<Integer, TopCentralProductType> productTypeMap,Map<Integer, List<TopCentralProductRelation>> productRelationGroupMap){

        Integer productId = (Integer) rootTree.getId();

        List<TopCentralProductRelation> topCentralProductRelations = productRelationGroupMap.get(productId);

        if(StringUtils.isNotEmpty(topCentralProductRelations)){
            for (TopCentralProductRelation topCentralProductRelation : topCentralProductRelations) {
                TopCentralProductType part = productTypeMap.get(topCentralProductRelation.getProductPartTypeId());

                if(StringUtils.isNotNull(part)){

                    Tree<TopCentralProductType> childTree = new Tree<>(part.getId(),part.getName(),part);

                    childTree.setParent(rootTree.getSource());
                    rootTree.appendChild(childTree);

                    fillParts(childTree,productTypeMap,productRelationGroupMap);
                }
            }
        }
    }
    
    /**
     * 采用获取所有数据 在进行有序划分的方法
     * 1.获取所有的产品类型
     * 2.根据参数：产品类型编号得到 根产品
     * 3.获取所有产品关系数据
     * 4.根据 根产品编号 递归获取子产品 及子产品的子产品 最终将子产品填充至 根产品对象中
     * @param productTypeId
     * @return
     */
    private ProductTree initProductTree(Integer productTypeId){
        //
        Map<Integer, TopCentralProductType> productTypeMap = selectAllMap();

        TopCentralProductType product = productTypeMap.get(productTypeId);

        ProductTree baseProductTree = new ProductTree(product);

        Map<? extends Serializable, TopCentralProductRelation> productRelationMap = productRelationService.selectAllMap();

        //selectAllMap 已修改为查询所有数据 除不可用数据
        //BaseEntityUtils.filterUnavailableData(productRelationMap);
        Map<Integer, List<TopCentralProductRelation>> productRelationGroupMap = productRelationMap.values().stream().collect(Collectors.groupingBy(TopCentralProductRelation::getProductTypeId));

        fillParts(baseProductTree,productTypeMap,productRelationGroupMap);

        return baseProductTree;
    }

    /**
     * 填充子产品
     * @param baseProductTree 父产品
     * @param productTypeMap 产品类型对象 k 产品类型编号 v 产品类型实体
     * @param productRelationGroupMap 产品关系对象 k 合成产品编号 v 合成产品子产品列表
     */
    private void fillParts(@NotNull ProductTree baseProductTree,@NotEmpty Map<Integer, TopCentralProductType> productTypeMap ,@NotEmpty Map<Integer,  List<TopCentralProductRelation>> productRelationGroupMap){

        Integer productTypeId = baseProductTree.getId();
        //判断当前产品是否由子产品 合成
        if(productRelationGroupMap.containsKey(productTypeId)){
            List<ProductTree> parts = new ArrayList<>();
            baseProductTree.setParts(parts);
            //获取合成当前产品的所有子产品
            List<TopCentralProductRelation> topCentralProductRelations = productRelationGroupMap.get(productTypeId);

            for (TopCentralProductRelation topCentralProductRelation : topCentralProductRelations) {
                //获取子产品的产品类型
                TopCentralProductType topCentralProductType = productTypeMap.get(topCentralProductRelation.getProductPartTypeId());

                ProductTree part = new ProductTree(topCentralProductType);
                //添加到子产品列表中
                parts.add(part);
                //判断当前子产品是否还有子产品
                fillParts(part,productTypeMap,productRelationGroupMap);
            }
        }

    }

    /**
     * 构建修改TopCentralProductType 的 修改类
     * @param id 产品类型主键
     * @param state 数据状态
     * @return TopCentralProductType构建的修改模型
     */
    private TopCentralProductType buildTopCentralProductTypeForUpdateState(Integer id, State state){

        TopCentralProductType topCentralProductType = new TopCentralProductType();
        topCentralProductType.setState(state);
        topCentralProductType.setId(id);

        return topCentralProductType;
    }

}
